import React from 'react';

import "./index.less"

/**
 * 贪吃蛇游戏
 * author：tzboy(Tzhack)
 */
class GreedySnake extends React.Component{
    constructor(props){
        super(props);

        const main_config = {
            // 游戏面板尺寸
            width       : 400,
            height      : 400,
            // 游戏面板 基础格子数{row:行，col列}
            base_num    : {
                row : 20,
                col : 20
            },
        };

        this.state = {
            // 游戏面板配置
            "main_config" : main_config,
            
            // 状态 0暂停，1运行，2结束
            "status" : 2,

            // 构建格子
            "list_lattice" : Array(main_config['base_num']['row']).fill([]).map(() => {
                return Array(main_config['base_num']['col']).fill({}).map(() => {
                    return { 
                        "track"  : false,
                    };
                })
            }),

            // 用户轨迹
            "user_track" : [],

            // 食物坐标点
            "eat_lattice" : {
                x : -1,
                y : -1
            },

            // 蛇神颜色
			"lattice_active_color" : {
				"r" : 0,
				"g" : 0,
				"b" : 0,
			},
			// 食物颜色
			"lattice_eat_color" : {
				"r" : 173,
				"g" : 119,
				"b" : 67,
            },
            
            // 行动规则
            "track_rule" : {
                "x" : 1, 
                "y" : 0
            },

            "speed":150, 
            
            "title":{
                "style" : "black",
                "value" : "Greedy snake",
            }

        }
        
    }

    componentDidMount(){
    	document.addEventListener("keydown", this.onKeyDown)
  	}

  	componentWillUnmount(){
    	document.removeEventListener("keydown", this.onKeyDown)
  	}

  	onKeyDown = (e) => {
  		if(this.state.status !== 1 ){
  			return false;
  		}
  		var track_rule = this.state.track_rule;

    	switch( e.keyCode) {
      		case 38:  // 上
      			if( track_rule.x === 1 && track_rule.y === 0 ){
      				return false;
      			}
      			track_rule.x = -1;
      			track_rule.y = 0;
        		break;
        	case 40:  // 下
        		if( track_rule.x === -1 && track_rule.y === 0 ){
      				return false;
      			}
                track_rule.x = 1;
      			track_rule.y = 0;
        		break;
        	case 37:  // 左
        		if( track_rule.x === 0 && track_rule.y === 1 ){
      				return false;
      			}
                track_rule.x = 0;
      			track_rule.y = -1;
        		break;
        	case 39:  // 右
        		if( track_rule.x === 0 && track_rule.y === -1 ){
      				return false;
      			}
                track_rule.x = 0;
      			track_rule.y = 1;
                break;
            default:
                break;
		}
		this.setState({"track_rule":track_rule});
	}

    /**
     * 渲染格子
     */
    buildGameLattice(){
        const main_config = this.state.main_config;

        // 用户轨迹
        var user_track = this.state.user_track;
        // 食物坐标
        var eat_lattice = this.state.eat_lattice;

        const lattice_active_color  = this.state.lattice_active_color;
        const lattice_eat_color     = this.state.lattice_eat_color;

        var lattice = {
            w : ( main_config['width'] || 0 ) / ( main_config['base_num']['col'] || 1 ),
            h : ( main_config['height'] || 0 ) / ( main_config['base_num']['row'] || 1 ),
        };
        var dom_arr = this.state.list_lattice.map((row_item,row_index)=>{
            return row_item.map((col_item,col_index)=>{
                let track_class = "";
                let style_track = "";
                
                // 向用户轨迹 写入样式
                for(var track_index in user_track){
                    var track = user_track[track_index];
                    if( track.x === row_index && track.y === col_index ){
                        track_class = "active";
                        var alpha = 1 - (track_index/user_track.length * 0.8);
						style_track = `rgba( ${ lattice_active_color.r }, ${ lattice_active_color.g }, ${ lattice_active_color.b }, ${ alpha })`;
                    }
                }
                // 向食物坐标点 写入样式
                if(eat_lattice){
					if( eat_lattice.x === row_index && eat_lattice.y === col_index ){
						style_track = `rgba( ${ lattice_eat_color.r }, ${ lattice_eat_color.g }, ${ lattice_eat_color.b },1`;
					}
                }
                
                return (
                    <div className={['lattice',track_class].join(" ")} key={row_index+"-"+col_index} style={
                        Object.assign({
                            width:lattice.w,
                            height:lattice.h
                        },{
                            backgroundColor:style_track,
                        })
                    }>
                    </div>
                )
            });
        });
        return dom_arr;
    }

    /**
     * 生成食物坐标点
     */
    setEatLattice(){
        var list_lattice = this.state.list_lattice;

        var user_track = this.state.user_track;

        // 存放可用食物坐标点
        var list_filter = [];
        for( var row_index in list_lattice ){
            for( var col_index in list_lattice[row_index] ){
                var can_use = true;
                for( var u of user_track){
                    if( u.x === row_index && u.y === col_index ){
                        can_use = false;
                        break;
                    }
                }
                if( can_use ){
                    list_filter.push( { 
                        "x" : parseInt(col_index), 
                        "y" : parseInt(row_index) 
                    } );
                }
            }
        }

        if(list_filter.length<=0){
            this.setState({"eat_lattice":{x:-1,y:-1}});
			return false;
        }
        
		var index = Math.floor((Math.random()*list_filter.length));
        var eat_lattice = list_filter[index];
		this.setState({"eat_lattice":eat_lattice});

    }

    /**
     * 初始化用户轨迹
     */
    initRrack(callBack=function(){}){
        var user_track = [
            { x : 5 , y : 6 },
            { x : 5 , y : 5 },
            { x : 5 , y : 4 },
            { x : 5 , y : 3 },
        ];

        this.setState({
            "user_track" : user_track
        },()=>{
            callBack();
        });
    }

    runRack(){
        if( parseInt(this.state.status) !== 1 ){
            return false;
        }

        var main_config = this.state.main_config;
        // 用户轨迹
        var user_track = (this.state.user_track||[]).slice();
        // 行动规则
        var track_rule = this.state.track_rule;

        if( user_track!=null && user_track.length>0 ){
            var user_header = Object.assign({},user_track[0]);
            user_header.x += track_rule.x;
            user_header.y += track_rule.y;
            if( user_header.x < 0 || user_header.y < 0 || user_header.x > ( main_config.base_num.col - 1 ) || user_header.y > ( main_config.base_num.row - 1 ) ){
                console.log("fail");
                this.opFail();
            }else{
                // 蛇尾巴
                var user_tail = Object.assign({},user_track[user_track.length-1]);

                // 蛇身轨迹 运动
                user_track = user_track.map((item,index)=>{
                    if( index === 0 ){
                        return item;
                    }
                    return user_track[index-1];
                });
                user_track[0] = user_header;

                // 碰撞检测
                var checkSelf = ()=>{
                    for(var track_index in user_track){
                        if( parseInt(track_index) !==0 ){
                            if( user_track[track_index]['x'] === user_header.x && user_track[track_index]['y'] === user_header.y ){
                                return false;
                            }
                        }
                    }
                    return true;
                }

                // 是否碰撞
                if(checkSelf()){
                    // 检测是否吃到食物
                    var eat_lattice = this.state.eat_lattice; // 食物坐标
                    if( user_header.x == eat_lattice.x && user_header.y == eat_lattice.y ){
                        console.error(eat_lattice,user_header);
                        user_track.push(user_tail);
                        this.setEatLattice();
                    }
                    this.setState({user_track:user_track});
                }else{
                    this.opFail();
                }
            }
        }else{
            this.opFail();
        }

        // 定时器
        if(this.state.status==1){
            this.timer_track = setTimeout(()=>{
                this.runRack();
            },this.state.speed);
        }
        
        
    }

    /**
     * 继续
     */
    opRun(){
        this.setState({
            status:1
        },()=>{
            this.runRack();
        });
        
    }

    /**
     * 停止
     */
    opStop(){
        this.setState({
            status:0
        });
    }
    /**
     * 设置失败
     */
    opFail(msg="挑战失败"){
        this.setState({
            status:2
        });
        React.$wa.showToast({
            "msg":msg,
            "mask":1,
            "theme":"red",
            "icon":'error',
        });
    }

    /**
     * 开始
     */
    opRef(){
        this.setState({
            status:1
        },()=>{
            // 初始化用户轨迹
            this.initRrack(()=>{
                 // 初始化食物
                this.setEatLattice();

                this.runRack();
            });
        });
       
    }

    /**
     * 构建游戏区域面板
     */
    buildGameRegion(){
        const main_config = this.state.main_config;
        const BuildGameOp = ()=>{
            var btnDom = null;
            if( this.state.status === 0 ){
                btnDom = ( <div className="btn blue" onClick={()=>{this.opRun()}}>继续</div> );
            }else if( this.state.status === 1 ){
                btnDom = ( <div className="btn gray" >加油~</div> );
            }else if( this.state.status === 2 ){
                btnDom = ( <div className="btn blue" onClick={()=>{this.opRef()}}>开始</div> );
            }
            return (
                <div className="game-ops">
                    {btnDom}
                </div>
            );
        }

        return (
            <div className="main-game" style={
                {
                    width:main_config.width,
                }
            }>
                <div className="game-title">
                    <span className={this.state.title.style}>{this.state.title.value}</span>
                </div>
                <BuildGameOp />
                <div className="game-content" style={
                    {
                        width:main_config.width,
                        height:main_config.height,
                    }
                }>
                    { this.buildGameLattice() }
                </div>
            </div>
        );
    }

    render(){
        return (
            <div className="tz-main">
                {  this.buildGameRegion() }
            </div>
        );
    }
}

export default GreedySnake;